package com.rzico.core.plugin.dada;


import com.alibaba.fastjson.JSON;
import com.rzico.core.entity.SysPlugin;
import com.rzico.core.model.PluginAttribute;
import com.rzico.core.plugin.RiderPlugin;
import com.rzico.core.rider.RiderApiRequest;
import com.rzico.core.rider.RiderApiResponse;
import com.rzico.core.utils.HttpClientUtil;
import com.rzico.core.utils.JSONUtil;
import com.rzico.util.MD5Utils;
import com.rzico.util.StringUtils;
import com.rzico.util.XMLUtils;
import io.swagger.annotations.ApiModelProperty;
import javafx.collections.transformation.SortedList;
import lombok.extern.slf4j.Slf4j;
import net.guerlab.sdk.anubis.entity.TransportInfo;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

@Component("dadaDeliverPlugin")
@Slf4j
public class DadaDeliverPlugin extends RiderPlugin {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    private final static String FORMAT = "json";

    private final static String V = "1.0";

    private final static String REQUEST_HOST = "http://newopen.imdada.cn";

    @Override
    public String getName() {
        return "达达配送";
    }


    @Override
    public String getVersion() {
        return "1.0";
    }

    /**
     * 向达达下单
     * @param orderAddRequest
     * @return
     */
    //添加订单
    private final static String REQUEST_URL_ADD_ORDER = "/api/order/addOrder";
    //查询运费
    private final static String REQUEST_URL_QUERY_DELIVER_FEE = "/api/order/queryDeliverFee";
    //订单详情查询
    private final static String REQUEST_URL_QUERY_ORDER_DETAIL = "/api/order/status/query";
    //取消订单
    private final static String REQUEST_URL_FORMAL_CANCEL = "/api/order/formalCancel";
    //订单取消原因(根据取消Id去查询)
    private final static String REQUEST_URL_FORMAL_CANCEL_REASONS = "/api/order/cancel/reasons";
    //查询追加配送员(追加订单)
    private final static String REQUEST_URL_APPOINT_LIST_TRANSPORTER = "/api/order/appoint/list/transporter";
    //追加订单
    private final static String REQUEST_URL_APPOINT_EXIST = "/api/order/appoint/exist";
    //追加订单取消
    private final static String REQUEST_URL_APPOINT_CANCEL = "/api/order/appoint/cancel";
    //妥投异常之物品返回完成
    private final static String REQUEST_URL_CONFIRM_GOODS = "/api/order/confirm/goods";

    @Override
    public List<PluginAttribute> getAttributeKeys() {

        List<PluginAttribute> data = new ArrayList<>();
        data.add(new PluginAttribute("app_key","appKey",PluginAttribute.STRING_VALUE));
        data.add(new PluginAttribute("app_secret","appSecret",PluginAttribute.STRING_VALUE));
        data.add(new PluginAttribute("source_id","sourceId",PluginAttribute.STRING_VALUE));
        return data;
    }

    /**
     * 提交订单
     *     private String status;
     *     private int code;
     *     private String msg;
     *     private String orderSn;
     *     private BigDecimal fee;
     *     private Integer statusCode;
     *     private Integer cancel_from;	//	订单取消原因来源(1:配送员取消；2:商家主动取消；3:系统或客服取消；0:默认值)
     *     private String dmName;	// 配送员姓名，接单以后会传
     *     private String dmMobile;	// 配送员手机号，接单以后会传
     *     private Double lat;// 配送员位置
     *     private Double lng;// 配送员位置
     */
    @Override
    public RiderApiResponse addOrder(SysPlugin sysPlugin, RiderApiRequest riderApiRequest) {
        String requestParams = null;
        Map<String,Object> paramsMap = null;

        if (riderApiRequest.getWeight() == null || BigDecimal.ZERO.equals(riderApiRequest.getWeight())) {
            riderApiRequest.setWeight(new BigDecimal(1));
        }
        paramsMap = convertToOrderMap(riderApiRequest);
        //paramsMap.put("callback","http://47.100.76.55:8765/order/dada/allnotify");
        paramsMap.put("callback",super.getNotifyUrl(sysPlugin));

        Date date =DateUtils.truncate(new Date(), Calendar.MINUTE);

        long currentTime = date.getTime();

        //获取预约时间
        long estimateTime = 0;
        String dateline = null;

        //获取预约时间,如果没有预约时间,默认是接单后10分钟开始配送
        if (riderApiRequest.getEstimateDate() == null) {
            dateline = (currentTime + 600000L) + "";
            dateline = dateline.substring(0, 10);
            paramsMap.put("delay_publish_time",dateline);
            logger.info("配送情况:[{}]" + "没有预约时间的情况下");
        }
        //有预约时间的情况下
        else if (riderApiRequest.getEstimateDate() != null) {
            //获取预约时间
            estimateTime = DateUtils.truncate(riderApiRequest.getEstimateDate(), Calendar.MINUTE).getTime();
            //estimateTime = riderApiRequest.getEstimateDate().getTime();
            //情况1: 如果estimateTime - cunrrentTIme > 35 以上
            if(estimateTime  > currentTime + 2100000L && estimateTime <= currentTime + 259200000L) {
                //保证不低于5分钟
                dateline = ((estimateTime - 1740000L) + "").substring(0, 10);
                //String finalDateline = dateline;
                //dateline = dateline.substring(0, 10);
                paramsMap.put("delay_publish_time",dateline);
                logger.info("配送情况:[{}]" + "情况1配送");
            }
            //情况2: 如果estimateTime - currentTime > 30  且 <35
            else if (estimateTime  >= currentTime + 1800000L  && estimateTime  <= currentTime + 2100000L) {
                //5分钟后接单,加一分钟,保证不低于5分钟
                dateline = (currentTime + 360000L) + "";
                dateline = dateline.substring(0, 10);
                paramsMap.put("delay_publish_time",dateline);
                logger.info("配送情况:[{}]" + "情况2配送");
            }
            //情况3: 如果estimateTime - currentTime < 30   且大于0
            else if (estimateTime < currentTime + 1800000L && estimateTime > currentTime) {
                //马上配送
                logger.info("配送情况:[{}]" + "情况3配送");
            }
            //情况4: 如果estimateTime < currentTime
            else if(estimateTime < currentTime) {
                //马上配送
                logger.info("配送情况:[{}]" + "情况4配送");
            }
            //情况5: estimateTime - currentTime > 3
            else if (estimateTime > currentTime + 259200000L) {
                return RiderApiResponse.error(0003,"预计送达时间不能超过三天", riderApiRequest.getOrderSn());
            }
        }

        String order_sn = (String) paramsMap.get("order_id");
        try {
            //获取签名
            requestParams = getRequestParams(sysPlugin, paramsMap);
        } catch (Exception e) {
            return RiderApiResponse.error(0003,"签名出错", order_sn);
        }

        //RiderApiResponse response = getResponse(requestUrl, requestParams);
        String resp = getResponse(REQUEST_URL_ADD_ORDER, requestParams);
        RiderApiResponse riderApiResponse = JSONUtil.fromJson(resp, RiderApiResponse.class);

        //riderApiResponse.setResult(null);
        if ("success".equals(riderApiResponse.getStatus())) {
            riderApiResponse.setOrderSn(order_sn);
            riderApiResponse.setFee((BigDecimal) riderApiResponse.getResult().get("fee"));
            riderApiResponse.setStatusCode(1);
            return riderApiResponse;
        } else {
            return RiderApiResponse.error(riderApiResponse.getCode(),riderApiResponse.getMsg(),order_sn);
        }
        //return commonRequest(REQUEST_URL_ADD_ORDER,sysPlugin,paramsMap,1);
    }

    /**
     * 计算运费
     */
    @Override
    public  RiderApiResponse calculateFee(SysPlugin sysPlugin, RiderApiRequest riderApiRequest) {
//        Map<String,Object> paramsMap = null;
//        paramsMap = convertToOrderMap(riderApiRequest);
//        return commonRequest(REQUEST_URL_QUERY_DELIVER_FEE,sysPlugin,paramsMap,2);
        String requestParams = null;
        Map<String,Object> paramsMap = null;
        if (riderApiRequest.getWeight() == null || BigDecimal.ZERO.equals(riderApiRequest.getWeight())) {
            riderApiRequest.setWeight(new BigDecimal(1));
        }
        paramsMap = convertToOrderMap(riderApiRequest);
        //paramsMap.put("callback",sysPlugin.getAttribute("callback"));
        //paramsMap.put("callback",sysPlugin.getAttribute("callback"));
        paramsMap.put("callback",super.getNotifyUrl(sysPlugin));
        String order_sn = (String) paramsMap.get("order_id");
        try {
            //获取签名
            requestParams = getRequestParams(sysPlugin, paramsMap);
        } catch (Exception e) {
            return RiderApiResponse.error(0003,"签名出错", order_sn);
        }

        //RiderApiResponse response = getResponse(requestUrl, requestParams);
        String resp = getResponse(REQUEST_URL_QUERY_DELIVER_FEE, requestParams);
        RiderApiResponse riderAPiResponse = JSONUtil.fromJson(resp, RiderApiResponse.class);
        //riderApiResponse.setResult(null);
        if ("success".equals(riderAPiResponse.getStatus())) {
            riderAPiResponse.setOrderSn(order_sn);
            riderAPiResponse.setFee((BigDecimal) riderAPiResponse.getResult().get("fee"));
            return riderAPiResponse;
        } else {
            return RiderApiResponse.error(riderAPiResponse.getCode(),riderAPiResponse.getMsg(),order_sn);
        }
    }

    /**
     * 订单取消
     * @param  sn 订单号，cancelReason 取消原因 , cancelReasonId 取消原因ID
     * @return
     */
    @Override
    public  RiderApiResponse cancel(SysPlugin sysPlugin, String sn,String cancelReason,Integer cancelReasonId) {
        Map<String,Object> paramsMap = new HashMap<>();
        paramsMap.put("order_id", sn);
        paramsMap.put("cancel_reason", cancelReason);
        paramsMap.put("cancel_reason_id", cancelReasonId);

        String requestParams = null;
        String order_sn = (String) paramsMap.get("order_id");
        try {
            //获取签名
            requestParams = getRequestParams(sysPlugin, paramsMap);
        } catch (Exception e) {
            return RiderApiResponse.error(0003,"签名出错", order_sn);
        }

        //RiderApiResponse response = getResponse(requestUrl, requestParams);
        String resp = getResponse(REQUEST_URL_FORMAL_CANCEL, requestParams);
        RiderApiResponse riderApiResponse = JSONUtil.fromJson(resp, RiderApiResponse.class);
        //riderApiResponse.setResult(null);
        if ("success".equals(riderApiResponse.getStatus())) {
            riderApiResponse.setOrderSn(order_sn);
            riderApiResponse.setFee((BigDecimal) riderApiResponse.getResult().get("deduct_fee"));
            return riderApiResponse;
        } else {
            return RiderApiResponse.error(riderApiResponse.getCode(),riderApiResponse.getMsg(),order_sn);
        }


    }

    /**
     * 查询订单详情   可跟踪骑手经纬度
     * @param sn
     * @return
     */
    @Override
    public  RiderApiResponse query(SysPlugin sysPlugin, String sn) {
        Map<String,Object> paramsMap = new HashMap<>();
        paramsMap.put("order_id", sn);
        //return commonRequest(REQUEST_URL_QUERY_ORDER_DETAIL,sysPlugin,paramsMap,4);
        String requestParams = null;
        String order_sn = (String) paramsMap.get("order_id");
        try {

            //获取签名
            requestParams = getRequestParams(sysPlugin, paramsMap);
        } catch (Exception e) {
            return RiderApiResponse.error(0003,"签名出错", order_sn);
        }

        //RiderApiResponse response = getResponse(requestUrl, requestParams);
        String resp = getResponse(REQUEST_URL_QUERY_ORDER_DETAIL, requestParams);
        RiderApiResponse riderApiResponse = JSONUtil.fromJson(resp, RiderApiResponse.class);
        //RiderApiResponse riderAPiResponse = null;
        //RiderApiResponse riderAPiResponse = null;
        if ("success".equals(riderApiResponse.getStatus())) {
            riderApiResponse.setOrderSn(order_sn);
            //Double fee = (Double)response.getResult().get("deduct_fee") + (Double) response.getResult().get("deliveryFee");
            riderApiResponse.setStatusCode((Integer) riderApiResponse.getResult().get("statusCode"));
            riderApiResponse.setFee((BigDecimal) riderApiResponse.getResult().get("deliveryFee"));
            //response.setFee((BigDecimal) response.getResult().get("deduct_fee"));
            riderApiResponse.setCancel_from((Integer) riderApiResponse.getResult().get("cancelFrom"));
            riderApiResponse.setDmName((String) riderApiResponse.getResult().get("transporterName"));
            riderApiResponse.setDmMobile((String) riderApiResponse.getResult().get("transporterPhone"));
            String lat = (String) riderApiResponse.getResult().get("transporterLat");
            String lng = (String) riderApiResponse.getResult().get("transporterLng");
            if (StringUtils.isNotBlank(lat) && StringUtils.isNotBlank(lng)) {
                riderApiResponse.setLat(Double.valueOf(lat) );
                riderApiResponse.setLng(Double.valueOf(lng) );
            }
            return riderApiResponse;
        } else {
            return RiderApiResponse.error(riderApiResponse.getCode(),riderApiResponse.getMsg(),order_sn);
        }
    }

    /**
     * 异常通知检查
     */
    @Override
    public  RiderApiResponse verifyNotify(SysPlugin sysPlugin, HttpServletRequest request) {
        //TODO
        HashMap<String, Object> finalpackage = new HashMap<>();
        //System.out.println("........................进入allnotify2.......................");
        RiderApiResponse riderApiResponse = null;
        try {
            riderApiResponse = new RiderApiResponse();
            HashMap<String, Object> resultMap = new HashMap<String, Object>();
            StringBuffer info = new StringBuffer();
            InputStream in = request.getInputStream();
            BufferedInputStream buf = new BufferedInputStream(in);
            byte[] buffer = new byte[1024];
            int iRead;
            while ((iRead = buf.read(buffer)) != -1) {
                info.append(new String(buffer, 0, iRead, "UTF-8"));
            }
            System.out.println("........................输出info:   " + info.toString());
            //resultMap = XMLUtils.xmlToMap(info.toString());
            Map parse = (Map) JSON.parse(info.toString());
            Integer orderStatus = (Integer) parse.get("order_status");
            String orderId = (String) parse.get("order_id");
            String dmMobile = (String) parse.get("dm_mobile");
            String name = (String) parse.get("dm_name");
            String cancelReason = (String) parse.get("cancel_reason");
            String updateTime = String.valueOf(parse.get("update_time"));
            String clientId = (String) parse.get("client_id");
            riderApiResponse.setOrderSn(orderId);
            riderApiResponse.setStatusCode(orderStatus);
            riderApiResponse.setDmMobile(dmMobile);
            riderApiResponse.setDmName(name);
            riderApiResponse.setMsg(cancelReason);
            String signature = (String) parse.get("signature");

            //验证 signature.equals(signaturV);
//            Map<String, Object> map = new HashMap<>();
//            map.put("client_id",client_id);
//            map.put("order_id",orderId);
//            map.put("update_time",updateTime);
            //String mysign = getSign(map, sysPlugin);
            //拼参数字符串。
            StringBuilder signStr = new StringBuilder();
            List<String> list =  new ArrayList<>();
            list.add(orderId);
            list.add(updateTime);
            list.add(clientId);
            list.sort((a,b) -> a.compareTo(b));
            list.forEach((a) -> signStr.append(a));
            //MD5签名并校验
            String toSign =signStr.toString();
            String sign = this.encrypt(toSign);

            boolean equals = sign.equals(signature);
            if (!equals) {
                RiderApiResponse riderApiResponse1 = new RiderApiResponse();
                riderApiResponse1.setCode(9999);
                riderApiResponse1.setMsg("签名错误");
                return riderApiResponse1;
            }
            if (orderStatus == 1000) {
                riderApiResponse.setCode(9999);
            } else {
                riderApiResponse.setCode(0);
            }
        } catch (Exception e) {
            RiderApiResponse riderApiResponse1 = new RiderApiResponse();
            riderApiResponse1.setCode(9999);
            riderApiResponse1.setMsg(e.getMessage());
            return riderApiResponse1;
        }
        return riderApiResponse;
    }

    //达达异常通知回复的字符串
    @Override
    public String getNotifyMessage(HttpServletRequest request) {
        //return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        String s = "{'status':'ok'}";
        return s;
    }


    //获取签名
    public  String  getRequestParams(SysPlugin sysPlugin,Map map) {
        HashMap<String, Object> packageParams = new HashMap<>();
        packageParams.put("source_id", sysPlugin.getAttribute("source_id"));
        packageParams.put("app_key", sysPlugin.getAttribute("app_key"));
        packageParams.put("timestamp", String.valueOf(System.currentTimeMillis()));
        packageParams.put("format", FORMAT);
        packageParams.put("v", V);
        packageParams.put("body", JSONUtil.toJson(map));
        packageParams.put("signature", this.getSign(packageParams,sysPlugin));
        return JSONUtil.toJson(packageParams);
    }

    public String getSign(Map<String, Object> requestParams,SysPlugin sysPlugin){

//        String str = joinKeyValue(params,"&",true,"sign","key");
//        // 签名步骤二：在string后加入KEY
//        if ("1".equals(sysPlugin.getAttribute("method"))) {
//            str += "&key=" + sysPlugin.getAttribute("key");
//        } else {
//            str += "&key=" + wx_mch_secret;
//        }
//        // 签名步骤三：MD5加密 签名步骤四：所有字符转为大写
//        str = MD5Utils.getMD5Str(str).toUpperCase();
//        return str;

        //请求参数键值升序排序
        Map<String, Object> sortedParams = new TreeMap<String, Object>(requestParams);
        Set<Map.Entry<String, Object>> entrySets = sortedParams.entrySet();

        //拼参数字符串。
        StringBuilder signStr = new StringBuilder();
        for (Map.Entry<String, Object> entry : entrySets) {
            signStr.append(entry.getKey()).append(entry.getValue());
        }

        //MD5签名并校验
        String toSign = sysPlugin.getAttribute("app_secret") + signStr.toString() + sysPlugin.getAttribute("app_secret");
        String sign = this.encrypt(toSign);
        return sign.toUpperCase();
    }

    public String encrypt(String inbuf)  {
        String s = null;
        char[] hexDigits = { // 用来将字节转换成 16 进制表示的字符
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            md.update(inbuf.getBytes("UTF-8"));
            byte tmp[] = md.digest(); // MD5 的计算结果是一个 128 位的长整数，
            // 用字节表示就是 16 个字节
            char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话，使用两个字符，
            // 所以表示成 16 进制需要 32 个字符
            int k = 0; // 表示转换结果中对应的字符位置
            for (int i = 0; i < 16; i++) { // 从第一个字节开始，对 MD5 的每一个字节
                // 转换成 16 进制字符的转换
                byte byte0 = tmp[i]; // 取第 i 个字节
                str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换,
                // >>> 为逻辑右移，将符号位一起右移
                str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
            }
            s = new String(str); // 换后的结果转换为字符串

        } catch (Exception e) {
            e.printStackTrace();
        }
        return s;
    }

    //通用模块代码
    public  String getResponse(String url,String requestParams) {
        String requestUrl = REQUEST_HOST + url;

        try {
            String resp = HttpClientUtil.postRequest(requestUrl, requestParams);
            //return JSONUtil.fromJson(resp, RiderApiResponse.class);
            return resp;
        }catch (Exception e){
            return "请求达达超时";
        }
    }

    private Map<String, Object> convertToOrderMap(RiderApiRequest orderAddRequest) {
        Map<String,Object> map = new HashMap<>();
        map.put("shop_no",orderAddRequest.getShopNo());

        map.put("origin_id",orderAddRequest.getOrderSn());
        map.put("city_code",orderAddRequest.getAreaId());
        map.put("cargo_price",orderAddRequest.getAmountPayable());
        map.put("receiver_name",orderAddRequest.getConsignee());
        map.put("receiver_address",orderAddRequest.getAddress());
        map.put("receiver_phone",orderAddRequest.getPhone());
        map.put("receiver_lat",orderAddRequest.getLat());
        map.put("receiver_lng",orderAddRequest.getLng());
        map.put("order_id",orderAddRequest.getOrderSn());

        map.put("cargo_weight",orderAddRequest.getWeight());
        map.put("cargo_num",orderAddRequest.getQuantity());
        map.put("pick_up_pos",orderAddRequest.getNum());

        if (orderAddRequest.getProductList() != null && orderAddRequest.getProductList().size() > 0) {
            List<Object>  pl = new ArrayList();
            orderAddRequest.getProductList().forEach((a) -> {
                Map<String,Object> productMap = new HashMap<>();
                productMap.put("sku_name",a.getName());
                productMap.put("src_product_no", a.getSn());
                productMap.put("count",a.getQuantity());
                productMap.put("unit",a.getUnit());
                pl.add(productMap);
            });
            map.put("product_list",pl);
        }

//        @ApiModelProperty(value = "货号/条码")
//        protected String sn;
//        @ApiModelProperty(value = "商品名称")
//        protected String name;
//        @ApiModelProperty(value = "单位")
//        protected String unit;
//        @ApiModelProperty(value = "数量")
//        protected BigDecimal quantity;
        return map;
    }




}
